import {Application, scheduleJob} from "pinus";
import {ControlService} from "../../services/controlService";
import {weight, genUserIds, genUsername, multiple, randomNumber,  genBetCount} from "./algorithm";

let robot:Robot = null

export default function (app: Application) {
    if (robot === null) {
        robot = new Robot(app)
    }
    return robot
}

export class Robot {
    private _robotInfos: {userId: number,username: string,index: number,betCount: number, multiple: number, auto:boolean, cashOut: boolean}[]
    private _statusJob: number;
    private _controlService: ControlService
    private _robotConfig: {multipleRange:{minMultiple: number, maxMultiple: number, chance: number, base: number}[],betRange:{minMultiple: number,maxMultiple: number,chance: number, base: number}[], bettingOdds: number,robotNumber: number}
    private _gameConfig: {minBet: number, maxBet: number, minMultiple: number, maxMultiple: number}
    private _probability: {section: {maxMultiple: number, minMultiple: number, startSection: number, lastSection:number,base: number}[], lastSection: number}
    private _betRange: {section: {maxMultiple: number, minMultiple: number, startSection: number, lastSection:number,base: number}[], lastSection: number}
    private _status: boolean
    constructor(private app: Application) {
        this._controlService = app.get('controlService')
        this._robotInfos = []
        this._status = false

    }

    public async init(): Promise<boolean>{
        if (!await this.resetGame()){
            return false
        }
        if(!await this.resetRobot()){
            return false
        }
        return this.reset()
    }

    private async reset(): Promise<boolean>{
        this._robotInfos = []
        this._probability = weight(this._robotConfig.multipleRange);
        this._betRange = weight(this._robotConfig.betRange);
        const userIds = genUserIds(this._robotConfig.robotNumber)
        userIds.forEach(e => {
            this._robotInfos.push({userId: e, username: genUsername(), index: 0, betCount: 0, multiple: 0, auto: true, cashOut: false})
        })
        this._status = true
        return true
    }

    public async resetRobot(): Promise<boolean>{
        const robotConfig  = await this._controlService.getRobotConfig()
        if (!robotConfig){
            return false
        }
        this._robotConfig = robotConfig
        return this.reset()
    }

    public async resetGame(): Promise<boolean>{
        const gameConfig = await this._controlService.getGameConfig()
        if (!gameConfig){
            return false
        }
        this._gameConfig = gameConfig
        return true
    }

    public async bet(times: number){
        if (!this._status){
            return
        }
        const aviatorServer = this.app.getServersByType('aviator')
        let task = []
        // 开始下注
        this._robotInfos.forEach(e => {
                e.index = 1
                // e.betCount = randomMultiple(this._gameConfig.minBet/100,this._gameConfig.maxBet/100) === 0 ? this._gameConfig.minBet : randomMultiple(this._gameConfig.minBet/100,this._gameConfig.maxBet/100) // 根据后台策略获取下注金额
                const betCount = genBetCount(this._betRange)
                e.betCount = betCount > this._gameConfig.maxBet? this._gameConfig.maxBet: betCount < this._gameConfig.minBet? this._gameConfig.minBet: betCount
                e.multiple = multiple(this._probability)  // 根据配置获取倍数
                e.auto  = true
                e.cashOut = false
        })
        this._robotInfos.sort(function(b,a){return 0.5-Math.random()})
        let beginIndex = 0;
        this._statusJob = scheduleJob({
            start: Date.now() + 200,
            period: 500,
            count: (times / 500)
        }, () => {
            let betCount = randomNumber(1,4)
            const betRobot = this._robotInfos.slice(beginIndex, betCount + beginIndex);
            beginIndex += betCount
            betRobot.forEach(e => {
                task.push(this.app.rpc.aviator.remote.robotBet.toServer(aviatorServer[0].id, e))
            })
        });
        return await Promise.all(task)
    }

}
